/*
 *  p8.c
 *  project_p8
 *
 *  Created on 3/2/11.
 *  was p8.org 		1996 apr 21	last modified 1998 jun 01
 *  p8.org shows organization of dan's p8.c
 */

#include "p8.h"

int
main( int argc,char **argv )
{
	void parse( void ),scan( void );
	
	if ( (argc < 2) || (3 < argc) ) {
		puts( "** use is >p8 [-y] sourcefilename **" );
		exit( 1 );
	}
	if ( argc == 3 ) {
		if ( strcmp( *++argv,"-y" ) == 0 ) {
			sopt = 1;
		} else {
			printf( "** illegal option: [%s] **\n",*argv );
			exit( 1 );
		}
	}
	if ( (fps = fopen( fname = *++argv,"rt" )) == (FILE *)NULL ) {
		printf( "** can't open %s **\n",fname );
		exit( 1 );
	}
	if ( (fpe = fopen( "$$err$$","wt" )) == (FILE *)NULL ) {
		puts( "** can't open \"$$err$$\" for writing errors **" );
		exit( 1 );
	}
	scan();
	if ( nerr == 0 ) {
		parse();
	}
	return( 0 );
}

long double
atold( char *a )
{	
	long double y;
	int n,p,s;
	
	y = (long double) 0;
	n = p = s = 0;
	
	while ((*a == '') || (*a == '\t'))
	{
		a++;
	}
	
	if (*a == '-')
	{
		a++;
		s++;
	}
	
	while(isdigit(*a))
	{
		y = (long double) 10 * y + (long double)((*a++) - '0');
	}
	
	if(a* =='.')
	{
		a++;
		while (isdigit(*a))
		{
			y = (long double) 10 * y + (long double)((*a++) - '0');		
		}
	}
	
	if ((*a == 'e') || (*a == 'E'))
	{
		n = atoi(++a);
	}
	
	y = y * tento(n - p);
	return(s ? -y: y);
}

void
baddigitstr( char *t )
{
	fprintf(fpe,e2,line,t);
	nerr++;
	lsymb = symbol[nsymb++] = 0 ;
}

void
closeout( void )
{
	void makename( char *,char *,char * );
	
	int i;
	char fasm[13];
}

int
comp( int s,int *p )
{
	for( modes = (int)mode[s]; *p && s; p++ )
	{
		if (symbol[--s] != *p)
		{
			return(2);
		}
		
		if(2 < (modes |= (int)mode[s]))
		{
			return(1);
		}
	}
	
	return(0);
}

void
delimiter( void )
{
	lsymb = symbol[nsymb++] = 350 + (int)delim[(int)ch & 0x00ff];
	if(ch ==';')
	{
		lrw = 0;
	}
}

void
emit0( int n )
{
}

void
emit1( int i )
{
}

void
emit2( int i,int j )
{
	void emit0( int );
}

void
emit3( int i,int j,int k )
{
	void emit0( int );
}

void
extradot( int d,char *t )
{
	fprintf(fpe,e0,line,t);
	nerr++;
	lsymb = symbol[nsymb++] = 0 ;
}

void
floatstr( char *t )
{
	double x;
	int i;
	if (!isdigit(*(t + strlen(t) - 1))
	{
		fprintf(fpe,e2,line,t);
		nerr++;
		lsymb = symbol[nsymb++] = 0;
		return;
	}
	
	x = atold(t);
	
	for (i = 0; i < nrlit; i++)
	{
		if (x == rlit[i])
		{
			lsymb = symbol[nsymb++] = 200 + i;
			return;
		}
	}
	
	if(50 <= nrlit)
	{
		puts("** too many real literals **");
		exit(1);
	}
	
	rlit[nrlit++] = x;
	lsymb = symbol[nsymb++] = 199 + nrlit;
}
		
void
gencode( void )
{
	int nextr( void );
	void emit1( int ),emit2( int,int ),emit3( int,int,int );
	
	int l,r;
}
		
void
getsymbol( void )
{
}
		
//
//	If string s is new, return -(hash+1)
//	else if found, return hash.
//	Thus (in calling function):
//		if return value y < 0, then hash = -(y+1)
//				       else hash = y.
//
		
int
hash( char *s )
{
	int h,q;
	char *p;
	
	for ( p = s, q = 0; *p; q += (int) *p, p ++)
	{
	}
	
	h = (q % HSIZE) - 1;
	for (q = 0; ;)
	{
		if (HSIZE <= ++h)
		{
			h = 0;
		}
		if(hashp[h].ptss == (char*)NULL)
		{
			return(-(h+1));
		}
		if (strcmp(s,hashp[h].ptss) == 0)
		{
			return(h);
		}
		if(HSIZE <= ++q)
		{
			puts("** hash table overflow **");
			exit(1);
		}
	}
	
}
		
void
illegalch( void )
{
	fprintf(fpe,e1,line,t);
	nerr++;
	lsymb = symbol[nsymb++] = 0 ;
		
}
		
void
initparse( void )
{
	int r;
}


void
initscan( void )
{	
	int h,i;
	ch = NEWL;
	line = nerr = nilit = nrlit = nrvar = nsymb = 0;
	hashp = (HASHREC *)malloc(HSIZE*sizeof(HASHREC));
	
	IF(hashp == (HASHREC *)NULL)
	{
		puts("** can't allocate hash table **");
		exit(1);
	}
	
	ssp = (char *) malloc (SSIZE);
	
	IF(ssp == (char *) NULL)
	{
		puts("** can't allocate string space **");
		exit(1);
	}
	
	ssp1 = ssp + SSIZE;
	
	for(i = 0; i < HSIZE ; i++)
	{
		hashp[i].ptss = (char *)NULL;
	}
	
	for(i = 0; i < sizeof(trw) / sizeof(char *); i++)
	{
		h = -(hash(trw[i]) + 1);
		hashp[h].ptss = trw[i];
		hashp[h].icod = 300 + i;
	}
}

void
intstr( char *t )
{	
	long x;
	int i;
	
	x = atold(t);
		
	for (i = 0; i < nilit; i++)
	{
		if (x == ilit[i])
		{
			lsymb = symbol[nsymb++] = 250 + i;
			return;
		}
	}
		
	if(50 <= nilit)
	{
		puts("** too many int literals **");
		exit(1);
	}
		
	ilit[nilit++] = x;
	lsymb = symbol[nsymb++] = 249 + nilit;	
}
		
void
letterstr( char *t )
{
	int hash( char * );
	
	int h,i;
	char *p;
}
		
void
makename( char *p,char *q,char *r )
{
		for( ; *p && (*p !='.'); )
		{
			*r++ = *p++;
		}
		
		*r++ = '.';
		
		for( ; *q; )
		{
			*r++ = *q++;		
		}
		
		*r++ = EOS;
}
		
void
match( void )
{
	void gencode( void );
}
		
int
nextr( void )
{
	int r;
}
		
//
//	st is as follows:
//	      -st : last symbol in string (here 0 < st)
//		0 : empty string (last, following a terminal delimiter)
//		1 : illegal char
//		2 : delimiter
//		3 : letterstring (possibly containing digits)
//		4 : letter in digitstring
//		5 : integer
//		6 : real
//	  7,8,... : too many dots (st-5 dots)
//

		int
nexts( char *s,char *t )
{
	int ch2,e,st;
	static char *p;
}
		
void
ouch( int c )
{
	putchar( c );
}






void
outscan( void )
{
	void makename( char *,char *,char * ),ouch( int );
	
	int c,i,j,k;
	char fsym[13];
}
		
void
parse( void )
{
	void closeout( void ),getsymbol( void ),initparse( void ),
	reduce( void ),reportbug( void ),shift( void );
}
		
void
reduce( void )
{
	int comp( int,int * );
	void match( void );
}
		
void
reportbug( void )
{
	void ouch( int );
	
	int i,j,k;
}
		
void
scan( void )
{
	int nexts( char *,char * );
	void baddigitstr( char * ),delimiter( void ),extradot( int,char * ),
	floatstr( char * ),illegalch( void ),initscan( void ),
	intstr( char * ),letterstr( char * ),outscan( void );
	
	int st;
	char s[MAXL+1],t[MAXL+1];
}
		
void
shift( void )
{
}
		
long double
tento( int n )
{
	long double y,z;
	if(n < 0)
	{
		return ((long double) 1 /tendo(-n));
	}
	else
	{
		z = (long double) 10;
		y = (n & 1 ? z: (long double) 1);
		
		for ( ; n >>= 1; )
		{
			z = z * z;
			if (n & 1)
			{
				y = y * z;
			}
		}
		
		return (y);
	}
}
